/*
 * Copyright (C) 2021 by Intel Corporation
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 */

#include <immintrin.h>

#include "qword_avx512.h"

void qword_avx512_intrinsics(const int64_t *a, const int64_t *b, int64_t *c,
			     uint64_t count)
{
	int N = (int)count;

	for (int i = 0; i < N; i += 32) {
		__m512i aa, bb, mul, sum;
		// #pragma unroll(4)
		for (int j = 0; j < 4; j++) {
			aa = _mm512_loadu_si512(
			    (const __m512i *)(a + i + 8 * j));
			bb = _mm512_loadu_si512(
			    (const __m512i *)(b + i + 8 * j));
			sum = _mm512_add_epi64(aa, bb);
			mul = _mm512_mullo_epi64(aa, bb);
			aa = _mm512_max_epi64(sum, mul);
			_mm512_storeu_si512((__m512i *)(c + 8 * j), aa);
		}
		c += 32;
	}
}
